//
// C++ Implementation: interrupts
//
// Description: Interrupts dump.
//
//
// Author: Andrey Sharoyko <vanyamboe@gmail.com>, (C) 2011
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "dumpdebug.h"
#include "interrupts.h"
#include "printpgm.h"

#if defined(DUMP_ARDUINO)

#define DUMP_INT_COUNT 26

prog_char irqVect0[] PROGMEM = { "RESET" };
prog_char irqVect1[] PROGMEM = { "INT0" };
prog_char irqVect2[] PROGMEM = { "INT1" };
prog_char irqVect3[] PROGMEM = { "PCINT0" };
prog_char irqVect4[] PROGMEM = { "PCINT1" };
prog_char irqVect5[] PROGMEM = { "PCINT2" };
prog_char irqVect6[] PROGMEM = { "WDT" };
prog_char irqVect7[] PROGMEM = { "TIMER2_COMPA" };
prog_char irqVect8[] PROGMEM = { "TIMER2_COMPB" };
prog_char irqVect9[] PROGMEM = { "TIMER2_OVF" };
prog_char irqVect10[] PROGMEM = { "TIMER1_CAPT" };
prog_char irqVect11[] PROGMEM = { "TIMER1_COMPA" };
prog_char irqVect12[] PROGMEM = { "TIMER1_COMPB" };
prog_char irqVect13[] PROGMEM = { "TIMER1_OVF" };
prog_char irqVect14[] PROGMEM = { "TIMER0_COMPA" };
prog_char irqVect15[] PROGMEM = { "TIMER0_COMPB" };
prog_char irqVect16[] PROGMEM = { "TIMER0_OVF" };
prog_char irqVect17[] PROGMEM = { "SPI STC" };
prog_char irqVect18[] PROGMEM = { "USART RX" };
prog_char irqVect19[] PROGMEM = { "USART UDRE" };
prog_char irqVect20[] PROGMEM = { "USART TX" };
prog_char irqVect21[] PROGMEM = { "ADC" };
prog_char irqVect22[] PROGMEM = { "EE READY" };
prog_char irqVect23[] PROGMEM = { "ANALOG COMP" };
prog_char irqVect24[] PROGMEM = { "TWI" };
prog_char irqVect25[] PROGMEM = { "SPM READY" };

PROGMEM const char* irqVects[] = {
  irqVect0, irqVect1, irqVect2, irqVect3, irqVect4,
  irqVect5, irqVect6, irqVect7, irqVect8, irqVect9,
  irqVect10, irqVect11, irqVect12, irqVect13, irqVect14,
  irqVect15, irqVect16, irqVect17, irqVect18, irqVect19,
  irqVect20, irqVect21, irqVect22, irqVect23, irqVect24,
  irqVect25
};

#elif defined(DUMP_MEGA)

#define DUMP_INT_COUNT 57

prog_char irqVect0[] PROGMEM = { "RESET" };
prog_char irqVect1[] PROGMEM = { "INT0" };
prog_char irqVect2[] PROGMEM = { "INT1" };
prog_char irqVect3[] PROGMEM = { "INT2" };
prog_char irqVect4[] PROGMEM = { "INT3" };
prog_char irqVect5[] PROGMEM = { "INT4" };
prog_char irqVect6[] PROGMEM = { "INT5" };
prog_char irqVect7[] PROGMEM = { "INT6" };
prog_char irqVect8[] PROGMEM = { "INT7" };
prog_char irqVect9[] PROGMEM = { "PCINT0" };
prog_char irqVect10[] PROGMEM = { "PCINT1" };
prog_char irqVect11[] PROGMEM = { "PCINT2" };
prog_char irqVect12[] PROGMEM = { "WDT" };
prog_char irqVect13[] PROGMEM = { "TIMER2_COMPA" };
prog_char irqVect14[] PROGMEM = { "TIMER2_COMPB" };
prog_char irqVect15[] PROGMEM = { "TIMER2_OVF" };
prog_char irqVect16[] PROGMEM = { "TIMER1_CAPT" };
prog_char irqVect17[] PROGMEM = { "TIMER1_COMPA" };
prog_char irqVect18[] PROGMEM = { "TIMER1_COMPB" };
prog_char irqVect19[] PROGMEM = { "TIMER1_COMPC" };
prog_char irqVect20[] PROGMEM = { "TIMER1_OVF" };
prog_char irqVect21[] PROGMEM = { "TIMER0_COMPA" };
prog_char irqVect22[] PROGMEM = { "TIMER0_COMPB" };
prog_char irqVect23[] PROGMEM = { "TIMER0_OVF" };
prog_char irqVect24[] PROGMEM = { "SPI STC" };
prog_char irqVect25[] PROGMEM = { "USART0 RX" };
prog_char irqVect26[] PROGMEM = { "USART0 UDRE" };
prog_char irqVect27[] PROGMEM = { "USART0 TX" };
prog_char irqVect28[] PROGMEM = { "ANALOG COMP" };
prog_char irqVect29[] PROGMEM = { "ADC" };
prog_char irqVect30[] PROGMEM = { "EE READY" };
prog_char irqVect31[] PROGMEM = { "TIMER3_CAPT" };
prog_char irqVect32[] PROGMEM = { "TIMER3_COMPA" };
prog_char irqVect33[] PROGMEM = { "TIMER3_COMPB" };
prog_char irqVect34[] PROGMEM = { "TIMER3_COMPC" };
prog_char irqVect35[] PROGMEM = { "TIMER3_OVF" };
prog_char irqVect36[] PROGMEM = { "USART1 RX" };
prog_char irqVect37[] PROGMEM = { "USART1 UDRE" };
prog_char irqVect38[] PROGMEM = { "USART1 TX" };
prog_char irqVect39[] PROGMEM = { "TWI" };
prog_char irqVect40[] PROGMEM = { "SPM READY" };
prog_char irqVect41[] PROGMEM = { "TIMER4_CAPT" };
prog_char irqVect42[] PROGMEM = { "TIMER4_COMPA" };
prog_char irqVect43[] PROGMEM = { "TIMER4_COMPB" };
prog_char irqVect44[] PROGMEM = { "TIMER4_COMPC" };
prog_char irqVect45[] PROGMEM = { "TIMER4_OVF" };
prog_char irqVect46[] PROGMEM = { "TIMER5_CAPT" };
prog_char irqVect47[] PROGMEM = { "TIMER5_COMPA" };
prog_char irqVect48[] PROGMEM = { "TIMER5_COMPB" };
prog_char irqVect49[] PROGMEM = { "TIMER5_COMPC" };
prog_char irqVect50[] PROGMEM = { "TIMER5_OVF" };
prog_char irqVect51[] PROGMEM = { "USART2 RX" };
prog_char irqVect52[] PROGMEM = { "USART2 UDRE" };
prog_char irqVect53[] PROGMEM = { "USART2 TX" };
prog_char irqVect54[] PROGMEM = { "USART3 RX" };
prog_char irqVect55[] PROGMEM = { "USART3 UDRE" };
prog_char irqVect56[] PROGMEM = { "USART3 TX" };

PROGMEM const char* irqVects[] = {
  irqVect0, irqVect1, irqVect2, irqVect3, irqVect4,
  irqVect5, irqVect6, irqVect7, irqVect8, irqVect9,
  irqVect10, irqVect11, irqVect12, irqVect13, irqVect14,
  irqVect15, irqVect16, irqVect17, irqVect18, irqVect19,
  irqVect20, irqVect21, irqVect22, irqVect23, irqVect24,
  irqVect25, irqVect26, irqVect27, irqVect28, irqVect29,
  irqVect30, irqVect31, irqVect32, irqVect33, irqVect34,
  irqVect35, irqVect36, irqVect37, irqVect38, irqVect39,
  irqVect40, irqVect41, irqVect42, irqVect43, irqVect44,
  irqVect45, irqVect46, irqVect47, irqVect48, irqVect49,
  irqVect50, irqVect51, irqVect52, irqVect53, irqVect54,
  irqVect55, irqVect56
};

#else
#   error "TODO: Add board type support here."
#endif

prog_char jmps0x[] PROGMEM = { "jmp 0x" };
extern prog_char ss[] PROGMEM;

bool checkForBad(dump_addr_t addr)
{
    unsigned int tmp = pgm_read_word(addr);
    if (tmp == 0x940C) {
        tmp = pgm_read_word(addr+2);
        if (tmp == 0)
            return true;
    }
    return false;
}

void dumpInterrupts()
{
    dump_addr_t addr = 0;
    dump_addr_t cmd, op;
    dump_addr_t bad = 0;
    Serial.println();
    for (unsigned char n = 0; n < DUMP_INT_COUNT; ++n) {
        dumpAddr(addr);
        printPgm(ss);
        cmd = pgm_read_word(addr);
        addr += 2;
        op = pgm_read_word(addr);
        addr += 2;
        if (cmd == 0x940C) {
            unsigned int op2 = op * 2;
            printPgm(jmps0x);
            dumpAddr(op2);
            if (op && ! bad) {
                if (checkForBad(op2))
                    bad = op;
            }
        }
        else {
            dumpAddr(cmd);
            Serial.print(' ');
            dumpAddr(op);
        }
        Serial.print('\t');
        Serial.print((cmd == 0x940C && (op == 0 || bad == op)) ? ' ' : '*');
        printPgm(ss);
        printPgm(&(irqVects[n]));
        Serial.println();
    }
}
